package com.gravata.enigma.model;

import java.io.Serializable;
import java.util.regex.Pattern;

import android.annotation.SuppressLint;

import com.gravata.enigma.Utils;
import com.j256.ormlite.dao.ForeignCollection;
import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.table.DatabaseTable;

@DatabaseTable(tableName="regra")
public class Regra extends EntidadeAbstrata implements Comparable<Regra> {

	private static final long serialVersionUID = -7934240299339870858L;

	@DatabaseField(generatedId=true)
	private int id;

	@DatabaseField(canBeNull=false,columnName="name")
	private String name;

	@DatabaseField(canBeNull=false,columnName="ordem",unique=false)
	private int ordem;

	@DatabaseField(canBeNull=false,columnName="favorito",dataType=DataType.BOOLEAN)
	private boolean favorito;

	@DatabaseField(canBeNull=false,columnName="exclude",dataType=DataType.BOOLEAN)
	private boolean exclude;

	@DatabaseField(canBeNull=false,foreign=true,foreignAutoRefresh=true)
	private Profile profile;

	@ForeignCollectionField(eager=false)
	private ForeignCollection<Filtro> filtros;

	private Pattern regex, regexNegado;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public int getOrdem() {
		return ordem;
	}
	public void setOrdem(int ordem) {
		this.ordem = ordem;
	}

	public ForeignCollection<Filtro> getFiltros() {
		return filtros;
	}

	public Profile getProfile() {
		return profile;
	}
	public void setProfile(Profile profile) {
		this.profile = profile;
	}

	public boolean isFavorito() {
		return favorito;
	}
	public void setFavorito(boolean favorito) {
		this.favorito = favorito;
	}

	public boolean isExclude() {
		return exclude;
	}
	public void setExclude(boolean exclude) {
		this.exclude = exclude;
	}

	@SuppressLint("DefaultLocale")
	public String getReference() {
		if(favorito)
			return "#SERVICE 1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet";
		else
			return "#SERVICE 1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet."+Utils.removeAcentosEspacos(name.toLowerCase())+".tv\" ORDER BY bouquet";
	}

	public Filtro getFiltro(int position){
		int i=0;
		for(Filtro filtro: getFiltros()){
			if(i==position)
				return filtro;
			i++;
		}
		return null;
	}

	public boolean atende(Service service){
		/*
		if(!getRegex().pattern().isEmpty()){
			boolean atende=getRegex().matcher(service.getName()).find();
			if(atende){
				atende=!nega(service.getName());
			}
			Log.d("REGRA ATENDE "+atende,service.getName()+" - "+getRegex().pattern());
			return atende ;
		}
		return false;*/
		boolean check=false;
		for(Filtro filtro:getFiltros()){
			if(!filtro.isNegado()){
				boolean atende=true;

				if(filtro.getSatelite()!=null){
					if(filtro.getSatelite().equals(service.getTransponder().getSatelite())){
						atende=true;
					}
				}

				if(atende){
					if(filtro.getTransponder()!=null){
						atende=filtro.getTransponder().equals(service.getTransponder());
					}
				}

				if(atende){
					if(filtro.isHd()){
						atende=service.isHD();
					}
				}

				if(!atende)
					continue;

				atende=filtro.atende(service.getName());
				if(!check){
					check=atende;
				}

			}
		}

		if(check){
			check=false;
			for(Filtro filtro:getFiltros()){
				if(filtro.isNegado()){
					boolean atende=true;

					if(filtro.getSatelite()!=null){
						if(filtro.getSatelite().equals(service.getTransponder().getSatelite())){
							atende=true;
						}
					}

					if(atende){
						if(filtro.getTransponder()!=null){
							atende=filtro.getTransponder().equals(service.getTransponder());
						}
					}

					if(atende){
						if(filtro.isHd()){
							atende=service.isHD();
						}
					}

					if(!atende)
						continue;

					atende=filtro.atende(service.getName());
					if(!check){
						check=atende;
					}

				}
			}
			check=!check;
		}

		return check;

	}

	private boolean nega(String teste){
		if(!getRegexNegado().pattern().isEmpty())
			return getRegexNegado().matcher(teste).find();
		return false;
	}
	private Pattern getRegex() {
		if(regex==null){
			String tmp="";
			String sep="";
			for(Filtro filtro:getFiltros()){
				tmp+=sep+filtro.getPattern();
				if(sep.isEmpty())
					sep="|";
			}

			regex=Pattern.compile(tmp,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
		}
		return regex;
	}

	private Pattern getRegexNegado() {
		if(regexNegado==null){
			String tmp="";
			String sep="";
			for(Filtro filtro:getFiltros()){
				if(filtro.isNegado()){
					tmp+=sep+filtro.getPattern();
					if(sep.isEmpty())
						sep="|";
				}
			}

			regexNegado=Pattern.compile(tmp,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
		}
		return regexNegado;
	}


	public Regra() {
	}


	@Override
	public Serializable getId() {
		// TODO Auto-generated method stub
		return id;
	}

	@Override
	public int compareTo(Regra another) {
		if(getOrdem()==another.getOrdem())
			return 0;
		if(getOrdem()>another.getOrdem())
			return 1;
		else return -1;
	}
}